package org.groupg.practice;

import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.groupg.practice.antlr.*;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Main {
    public static void main(String[] args) throws Exception {
        String input = "指标A -> [10,20] -> 20\n" +
                       "指标A -> (20,30] -> 30\n" +
                       "指标B -> (-,20] -> 10\n" +
                       "指标B -> (20,30) -> 20\n" +
                       "计算结果= 指标A结果 * 30% + 指标B结果 * 10%";

        // 从字符串读取输入
        ANTLRInputStream inputStream = new ANTLRInputStream(input);

        // 创建词法分析器
        IndicatorLexer lexer = new IndicatorLexer(inputStream);

        // 创建缓冲区，生成token
        CommonTokenStream tokens = new CommonTokenStream(lexer);

        // 创建解析器
        IndicatorParser parser = new IndicatorParser(tokens);

        // 开始分析
        ParseTree tree = parser.prog();

        // 自定义监听器来处理解析树
        MyListener listener = new MyListener();
        ParseTreeWalker.DEFAULT.walk(listener, tree);

        // 计算结果
        double result = listener.calculateResult();
        System.out.println("计算结果: " + result);
    }
}

class MyListener extends ParseTreeListener {
    private Map<String, Double> results = new HashMap<>();
    private double calculationResult = 0.0;

    @Override
    public void enterIndicatorRule(IndicatorParser.IndicatorRuleContext ctx) {
        String id = ctx.ID().getText();
        double value = Double.parseDouble(ctx.NUMBER().getText());
        // 这里简单假设区间检查总是通过
        results.put(id + "结果", value);
    }

    @Override
    public void enterCalculationRule(IndicatorParser.CalculationRuleContext ctx) {
        // 解析表达式并计算
        calculationResult = evaluateExpr(ctx.expr());
    }

    private double evaluateExpr(IndicatorParser.ExprContext ctx) {
        if (ctx.MulDivExpr() != null) {
            return evaluateExpr(ctx.MulDivExpr());
        } else if (ctx.AddSubExpr() != null) {
            return evaluateExpr(ctx.AddSubExpr());
        } else if (ctx.VarRef() != null) {
            String varName = ctx.VarRef().ID().getText();
            return results.getOrDefault(varName, 0.0);
        } else if (ctx.PercentExpr() != null) {
            double value = evaluateExpr(ctx.PercentExpr().expr());
            return value / 100.0;
        } else if (ctx.ParenExpr() != null) {
            return evaluateExpr(ctx.ParenExpr().expr());
        } else if (ctx.Number() != null) {
            return Double.parseDouble(ctx.Number().getText());
        }
        return 0.0;
    }

    private double evaluateExpr(IndicatorParser.MulDivExprContext ctx) {
        double left = evaluateExpr(ctx.expr(0));
        double right = evaluateExpr(ctx.expr(1));
        if (ctx.op.getText().equals("*")) {
            return left * right;
        } else {
            return left / right;
        }
    }

    private double evaluateExpr(IndicatorParser.AddSubExprContext ctx) {
        double left = evaluateExpr(ctx.expr(0));
        double right = evaluateExpr(ctx.expr(1));
        if (ctx.op.getText().equals("+")) {
            return left + right;
        } else {
            return left - right;
        }
    }

    public double calculateResult() {
        return calculationResult;
    }
}